/**
 * 
 */
package it.unicam.fishpass.prism.parser;

import java.util.Arrays;

/**
 * Represents a generic multiarc on the graph, i.e. an arc with a single source
 * location and multiple destinations.
 * 
 * It is supposed that the probabilities added are correct, i.e. they sum up to
 * 1. It is also supposed that the arc names are consistent, i.e. there is NO
 * repetition in the names associated with each arc in the multiarc. All these
 * sanity checks are demanded to the caller.
 * 
 * @author Andrea Baiocco
 */
public class MultiArc {

	@SuppressWarnings("rawtypes")
	Pair[] arcs; // must be cast to Pair<String, Float> !!!
	int counter;

	/**
	 * 
	 * @param NumberOfArcs
	 */
	MultiArc(int NumberOfArcs) {
		arcs = new Pair[NumberOfArcs];
		counter = 0;
	}

	/**
	 */
	MultiArc(String target) {
		arcs = new Pair[] { new Pair<>(new Float(1), target) };
		counter = 1;
	}

	/**
	 * 
	 * @param label
	 * @param value
	 */
	void addArc(String label, float value) {
		if (counter >= arcs.length)
			throw new ArrayIndexOutOfBoundsException(
					"The arc is filled with all the probabilities");
		// else arc is added
		arcs[counter++] = new Pair<Float, String>(new Float(value), label);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(arcs);
		result = prime * result + counter;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (obj.getClass() != MultiArc.class)
			return false;
		//
		MultiArc other = (MultiArc) obj;
		if (counter != other.counter)
			return false;
		// else, iteration over the data structures for equality check
		for (int i = 0; i < counter; i++)
			if (!arcs[i].equals(other.arcs[i]))
				return false;
		return true;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < counter; i++)
		sb.append(arcs[i] + "  ");
		return sb.toString();
	}
}

/**
 * 
 * @author Andrea Baiocco
 * 
 * @param <A>
 * @param <B>
 */
class Pair<A, B> {
	A first;
	B second;

	Pair(A first, B second) {
		this.first = first;
		this.second = second;
	}

	@Override
	public int hashCode() {
		int hashFirst = first != null ? first.hashCode() : 0;
		int hashSecond = second != null ? second.hashCode() : 0;
		return (hashFirst + hashSecond) * hashSecond + hashFirst;
	}

	@Override
	public boolean equals(Object other) {
		if (other instanceof Pair) {
			@SuppressWarnings("rawtypes")
			Pair otherPair = (Pair) other;
			return ((this.first == otherPair.first || (this.first != null
					&& otherPair.first != null && this.first
						.equals(otherPair.first))) && (this.second == otherPair.second || (this.second != null
					&& otherPair.second != null && this.second
						.equals(otherPair.second))));
		}
		return false;
	}

	@Override
	public String toString() {
		return "(" + first + "|" + second + ")";
	}
}